home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint110s / pipefs.c < prev    next >
C/C++ Source or Header  |  1994-02-09  |  26KB  |  1,087 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1992,1993,1994 Atari Corporation.
  4. All rights reserved.
  5.  */
  6.  
  7. /* simple pipefs.c */
  8.  
  9. #include "mint.h"
  10.  
  11. static int pipetime, pipedate;    /* root directory time/date stamp */
  12.  
  13. static long    ARGS_ON_STACK pipe_root    P_((int drv, fcookie *fc));
  14. static long    ARGS_ON_STACK pipe_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  15. static long    ARGS_ON_STACK pipe_getxattr    P_((fcookie *file, XATTR *xattr));
  16. static long    ARGS_ON_STACK pipe_chattr    P_((fcookie *file, int attrib));
  17. static long    ARGS_ON_STACK pipe_chown    P_((fcookie *file, int uid, int gid));
  18. static long    ARGS_ON_STACK pipe_chmode    P_((fcookie *file, unsigned mode));
  19. static long    ARGS_ON_STACK pipe_rmdir    P_((fcookie *dir, const char *name));
  20. static long    ARGS_ON_STACK pipe_remove    P_((fcookie *dir, const char *name));
  21. static long    ARGS_ON_STACK pipe_getname    P_((fcookie *root, fcookie *dir,
  22.                             char *pathname, int size));
  23. static long    ARGS_ON_STACK pipe_rename    P_((fcookie *olddir, char *oldname,
  24.                     fcookie *newdir, const char *newname));
  25. static long    ARGS_ON_STACK pipe_opendir    P_((DIR *dirh, int flags));
  26. static long    ARGS_ON_STACK pipe_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  27. static long    ARGS_ON_STACK pipe_rewinddir    P_((DIR *dirh));
  28. static long    ARGS_ON_STACK pipe_closedir    P_((DIR *dirh));
  29. static long    ARGS_ON_STACK pipe_pathconf    P_((fcookie *dir, int which));
  30. static long    ARGS_ON_STACK pipe_dfree    P_((fcookie *dir, long *buf));
  31. static long    ARGS_ON_STACK pipe_creat    P_((fcookie *dir, const char *name, unsigned mode,
  32.                     int attrib, fcookie *fc));
  33. static DEVDRV *    ARGS_ON_STACK pipe_getdev    P_((fcookie *fc, long *devsp));
  34.  
  35. static long    ARGS_ON_STACK pipe_open    P_((FILEPTR *f));
  36. static long    ARGS_ON_STACK pipe_write    P_((FILEPTR *f, const char *buf, long bytes));
  37. static long    ARGS_ON_STACK pipe_read    P_((FILEPTR *f, char *buf, long bytes));
  38. static long    ARGS_ON_STACK pipe_lseek    P_((FILEPTR *f, long where, int whence));
  39. static long    ARGS_ON_STACK pipe_ioctl    P_((FILEPTR *f, int mode, void *buf));
  40. static long    ARGS_ON_STACK pipe_datime    P_((FILEPTR *f, short *time, int rwflag));
  41. static long    ARGS_ON_STACK pipe_close    P_((FILEPTR *f, int pid));
  42. static long    ARGS_ON_STACK pipe_select    P_((FILEPTR *f, long p, int mode));
  43. static void    ARGS_ON_STACK pipe_unselect    P_((FILEPTR *f, long p, int mode));
  44.  
  45. DEVDRV pipe_device = {
  46.     pipe_open, pipe_write, pipe_read, pipe_lseek, pipe_ioctl, pipe_datime,
  47.     pipe_close, pipe_select, pipe_unselect
  48. };
  49.  
  50. /* ptys and pipes can share the same driver, for now */
  51. #define pty_device pipe_device
  52.  
  53. FILESYS pipe_filesys = {
  54.     (FILESYS *)0,
  55.     0,
  56.     pipe_root,
  57.     pipe_lookup, pipe_creat, pipe_getdev, pipe_getxattr,
  58.     pipe_chattr, pipe_chown, pipe_chmode,
  59.     nomkdir, pipe_rmdir, pipe_remove, pipe_getname, pipe_rename,
  60.     pipe_opendir, pipe_readdir, pipe_rewinddir, pipe_closedir,
  61.     pipe_pathconf, pipe_dfree,
  62.     nowritelabel, noreadlabel, nosymlink, noreadlink,
  63.     nohardlink, nofscntl, nodskchng
  64. };
  65.  
  66. /* size of pipes */
  67. #define PIPESIZ    4096        /* MUST be a multiple of 4 */
  68.  
  69. /* writes smaller than this are atomic */
  70. #define PIPE_BUF 1024        /* should be a multiple of 4 */
  71.  
  72. /* magic flag: indicates that nobody but the creator has opened this pipe */
  73. /* note: if this many processes open the pipe, we lose :-( */
  74. #define VIRGIN_PIPE    0x7fff
  75.  
  76. struct pipe {
  77.     int    readers;    /* number of readers of this pipe */
  78.     int    writers;    /* number of writers of this pipe */
  79.     int    head, tail;    /* pipe head, tail (head == tail for empty) */
  80.     long    rsel;        /* process that did select() for reads */
  81.     long    wsel;        /* process that did select() for writes */
  82.     char    buf[PIPESIZ];    /* pipe data */
  83. };
  84.  
  85. struct fifo {
  86.     char    name[NAME_MAX+1]; /* FIFO's name */
  87.     short    date, time;    /* date & time of last write */
  88.     short    dosflags;    /* DOS flags, e.g. FA_RDONLY, FA_HIDDEN */
  89.     ushort    mode;        /* file access mode, for XATTR */
  90.     ushort    uid, gid;    /* file owner; uid and gid */
  91.     short    flags;        /* various other flags (e.g. O_TTY) */
  92.     short    lockpid;    /* pid of locking process */
  93.     short    cursrate;    /* cursor flash rate for pseudo TTY's */
  94.     struct tty *tty;    /* tty struct for pseudo TTY's */
  95.     struct pipe *inp;    /* pipe for reads */
  96.     struct pipe *outp;    /* pipe for writes (0 if unidirectional) */
  97.     struct fifo *next;    /* link to next FIFO in list */
  98.     FILEPTR *open;        /* open file pointers for this fifo */
  99. } *rootlist;
  100.  
  101.  
  102. static long ARGS_ON_STACK 
  103. pipe_root(drv, fc)
  104.     int drv;
  105.     fcookie *fc;
  106. {
  107.     if (drv == PIPEDRV) {
  108.         fc->fs = &pipe_filesys;
  109.         fc->dev = drv;
  110.         fc->index = 0L;
  111.         return 0;
  112.     }
  113.     fc->fs = 0;
  114.     return EINTRN;
  115. }
  116.  
  117. static long ARGS_ON_STACK 
  118. pipe_lookup(dir, name, fc)
  119.     fcookie *dir;
  120.     const char *name;
  121.     fcookie *fc;
  122. {
  123.     struct fifo *b;
  124.  
  125.     TRACE(("pipe_lookup(%s)", name));
  126.  
  127.     if (dir->index != 0) {
  128.         DEBUG(("pipe_lookup(%s): bad directory", name));
  129.         return EPTHNF;
  130.     }
  131. /* special case: an empty name in a directory means that directory */
  132. /* so does "." */
  133.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  134.         *fc = *dir;
  135.         return 0;
  136.     }
  137.  
  138. /* another special case: ".." could be a mount point */
  139.     if (!strcmp(name, "..")) {
  140.         *fc = *dir;
  141.         return EMOUNT;
  142.     }
  143.  
  144.     for (b = rootlist; b; b = b->next) {
  145.         if (!strnicmp(b->name, name, NAME_MAX)) {
  146.             fc->fs = &pipe_filesys;
  147.             fc->index = (long)b;
  148.             fc->dev = dir->dev;
  149.             return 0;
  150.         }
  151.     }
  152.     DEBUG(("pipe_lookup: name `%s' not found", name));
  153.     return EFILNF;
  154. }
  155.  
  156. static long ARGS_ON_STACK 
  157. pipe_getxattr(fc, xattr)
  158.     fcookie *fc;
  159.     XATTR *xattr;
  160. {
  161.     struct fifo *this;
  162.  
  163.     xattr->index = fc->index;
  164.     xattr->dev = fc->dev;
  165.     xattr->rdev = fc->dev;
  166.     xattr->nlink = 1;
  167.     xattr->blksize = 1;
  168.  
  169.     if (fc->index == 0) {        /* root directory? */
  170.         xattr->uid = xattr->gid = 0;
  171.         xattr->mtime = xattr->atime = xattr->ctime = pipetime;
  172.         xattr->mdate = xattr->adate = xattr->cdate = pipedate;
  173.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  174.         xattr->attr = FA_DIR;
  175.         xattr->size = xattr->nblocks = 0;
  176.     } else {
  177.         this = (struct fifo *)fc->index;
  178.         xattr->uid = this->uid;
  179.         xattr->gid = this->gid;
  180.         xattr->mtime = xattr->atime = xattr->ctime = this->time;
  181.         xattr->mdate = xattr->adate = xattr->cdate = this->date;
  182.         xattr->mode = this->mode;
  183.         xattr->attr = this->dosflags;
  184.     /* note: fifo's that haven't been opened yet can be written to */
  185.         if (this->flags & O_HEAD) {
  186.             xattr->attr &= ~FA_RDONLY;
  187.         }
  188.  
  189.         xattr->nblocks = PIPESIZ;
  190.         if (this->dosflags & FA_SYSTEM) {    /* pseudo-tty */
  191.             xattr->size = PIPESIZ/4;
  192.             xattr->rdev = PIPE_RDEV|1;
  193.         } else {
  194.             xattr->size = PIPESIZ;
  195.             xattr->rdev = PIPE_RDEV|0;
  196.         }
  197.     }
  198.     return 0;
  199. }
  200.  
  201. static long ARGS_ON_STACK 
  202. pipe_chattr(fc, attrib)
  203.     fcookie *fc;
  204.     int attrib;
  205. {
  206.     UNUSED(fc); UNUSED(attrib);
  207.     return EACCDN;
  208. }
  209.  
  210. static long ARGS_ON_STACK 
  211. pipe_chown(fc, uid, gid)
  212.     fcookie *fc;
  213.     int uid, gid;
  214. {
  215.     struct fifo *this;
  216.  
  217.     if ((this = (struct fifo *)fc->index) == 0)
  218.         return EACCDN;
  219.  
  220.     this->uid = uid;
  221.     this->gid = gid;
  222.     return 0;
  223. }
  224.  
  225. static long ARGS_ON_STACK 
  226. pipe_chmode(fc, mode)
  227.     fcookie *fc;
  228.     unsigned mode;
  229. {
  230.     struct fifo *this;
  231.  
  232.     if ((this = (struct fifo *)fc->index) == 0)
  233.         return EACCDN;
  234.  
  235.     this->mode = (this->mode & S_IFMT) | (mode & ~S_IFMT);
  236.     return 0;
  237. }
  238.  
  239. static long ARGS_ON_STACK 
  240. pipe_rmdir(dir, name)
  241.     fcookie *dir;
  242.     const char *name;
  243. {
  244.     UNUSED(dir); UNUSED(name);
  245.  
  246. /* the kernel already checked to see if the file exists */
  247.     return EACCDN;
  248. }
  249.  
  250. static long ARGS_ON_STACK 
  251. pipe_remove(dir, name)
  252.     fcookie *dir;
  253.     const char *name;
  254. {
  255.     UNUSED(dir); UNUSED(name);
  256.  
  257. /* the kernel already checked to see if the file exists */
  258.     return EACCDN;
  259. }
  260.  
  261. static long ARGS_ON_STACK 
  262. pipe_getname(root, dir, pathname, size)
  263.     fcookie *root, *dir; char *pathname;
  264.     int size;
  265. {
  266.     UNUSED(root);
  267.     UNUSED(size);    /* BUG: we should support 'size' */
  268.  
  269.     if (dir->index == 0)
  270.         *pathname = 0;
  271.     else
  272.         strcpy(pathname, ((struct fifo *)dir->index)->name);
  273.     return 0;
  274. }
  275.  
  276. static long ARGS_ON_STACK 
  277. pipe_rename(olddir, oldname, newdir, newname)
  278.     fcookie *olddir;
  279.     char *oldname;
  280.     fcookie *newdir;
  281.     const char *newname;
  282. {
  283.     UNUSED(olddir); UNUSED(oldname);
  284.     UNUSED(newdir); UNUSED(newname);
  285.  
  286.     return EACCDN;
  287. }
  288.  
  289. static long ARGS_ON_STACK 
  290. pipe_opendir(dirh, flags)
  291.     DIR *dirh;
  292.     int flags;
  293. {
  294.     UNUSED(flags);
  295.  
  296.     if (dirh->fc.index != 0) {
  297.         DEBUG(("pipe_opendir: bad directory"));
  298.         return EPTHNF;
  299.     }
  300.     dirh->index = 0;
  301.     return 0;
  302. }
  303.  
  304. static long ARGS_ON_STACK 
  305. pipe_readdir(dirh, name, namelen, fc)
  306.     DIR *dirh;
  307.     char *name;
  308.     int namelen;
  309.     fcookie *fc;
  310. {
  311.     struct fifo *this;
  312.     int i;
  313.     int giveindex = dirh->flags == 0;
  314.  
  315.     i = dirh->index++;
  316.     this = rootlist;
  317.     while (i > 0 && this) {
  318.         --i; this = this->next;
  319.     }
  320.     if (!this)
  321.         return ENMFIL;
  322.  
  323.     fc->fs = &pipe_filesys;
  324.     fc->index = (long)this;
  325.     fc->dev = dirh->fc.dev;
  326.     if (giveindex) {
  327.         namelen -= (int) sizeof(long);
  328.         if (namelen <= 0) return ERANGE;
  329.         *((long *)name) = (long)this;
  330.         name += sizeof(long);
  331.     }
  332.     strncpy(name, this->name, namelen-1);
  333.     if (strlen(this->name) >= namelen)
  334.         return ENAMETOOLONG;
  335.     return 0;
  336. }
  337.  
  338. static long ARGS_ON_STACK 
  339. pipe_rewinddir(dirh)
  340.     DIR *dirh;
  341. {
  342.     dirh->index = 0;
  343.     return 0;
  344. }
  345.  
  346. static long ARGS_ON_STACK 
  347. pipe_closedir(dirh)
  348.     DIR *dirh;
  349. {
  350.     UNUSED(dirh);
  351.     return 0;
  352. }
  353.  
  354. static long ARGS_ON_STACK 
  355. pipe_pathconf(dir, which)
  356.     fcookie *dir;
  357.     int which;
  358. {
  359.     UNUSED(dir);
  360.  
  361.     switch(which) {
  362.     case -1:
  363.         return DP_MAXREQ;
  364.     case DP_IOPEN:
  365.         return UNLIMITED;    /* no internal limit on open files */
  366.     case DP_MAXLINKS:
  367.         return 1;        /* no hard links */
  368.     case DP_PATHMAX:
  369.         return PATH_MAX;
  370.     case DP_NAMEMAX:
  371.         return NAME_MAX;
  372.     case DP_ATOMIC:
  373.     /* BUG: for pty's, this should actually be PIPE_BUF/4 */
  374.         return PIPE_BUF;
  375.     case DP_TRUNC:
  376.         return DP_AUTOTRUNC;
  377.     case DP_CASE:
  378.         return DP_CASEINSENS;
  379.     default:
  380.         return EINVFN;
  381.     }
  382. }
  383.  
  384. static long ARGS_ON_STACK 
  385. pipe_dfree(dir, buf)
  386.     fcookie *dir;
  387.     long *buf;
  388. {
  389.     int i;
  390.     struct fifo *b;
  391.     long freemem;
  392.  
  393.     UNUSED(dir);
  394.  
  395. /* the "sector" size is the number of bytes per pipe */
  396. /* so we get the total number of sectors used by counting pipes */
  397.  
  398.     i = 0;
  399.     for (b = rootlist; b; b = b->next) {
  400.         if (b->inp) i++;
  401.         if (b->outp) i++;
  402.     }
  403.  
  404.     freemem = tot_rsize(core, 0) + tot_rsize(alt, 0);
  405.  
  406. /* note: the "free clusters" isn't quite accurate, since there's overhead
  407.  * in the fifo structure; but we're not looking for 100% accuracy here
  408.  */
  409.     buf[0] = freemem/PIPESIZ;    /* number of free clusters */
  410.     buf[1] = buf[0]+i;        /* total number of clusters */
  411.     buf[2] = PIPESIZ;        /* sector size (bytes) */
  412.     buf[3] = 1;            /* cluster size (sectors) */
  413.     return 0;
  414. }
  415.  
  416. /* create a new pipe.
  417.  * this only gets called by the kernel if a lookup already failed,
  418.  * so we know that the new pipe creation is OK
  419.  */
  420.  
  421. static long ARGS_ON_STACK 
  422. pipe_creat(dir, name, mode, attrib, fc)
  423.     fcookie *dir;
  424.     const char *name;
  425.     unsigned mode;
  426.     int attrib;
  427.     fcookie *fc;
  428. {
  429.     struct pipe *inp, *outp;
  430.     struct tty *tty;
  431.     struct fifo *b;
  432. /* selfread == 1 if we want reads to wait even if no other processes
  433.    have currently opened the file, and writes to succeed in the same
  434.    event. This is useful for servers who want to wait for requests.
  435.    Pipes should always have selfread == 0.
  436. */
  437.     int selfread = (attrib & FA_HIDDEN) ? 0 : 1;
  438.  
  439.  
  440.     /* create the new pipe */
  441.     if (0 == (inp = (struct pipe *)kmalloc(SIZEOF(struct pipe)))) {
  442.         return ENSMEM;
  443.     }
  444.     if (attrib & FA_RDONLY) {    /* read only FIFOs are unidirectional */
  445.         outp = 0;
  446.     } else {
  447.         outp = (struct pipe *)kmalloc(SIZEOF(struct pipe));
  448.         if (!outp) {
  449.             kfree(inp);
  450.             return ENSMEM;
  451.         }
  452.     }
  453.     b = (struct fifo *)kmalloc(SIZEOF(struct fifo));
  454.     if (!b) {
  455.         kfree(inp);
  456.         if (outp) kfree(outp);
  457.         return ENSMEM;
  458.     }
  459.     if (attrib & FA_SYSTEM) {    /* pseudo-tty */
  460.         tty = (struct tty *)kmalloc(SIZEOF(struct tty));
  461.         if (!tty) {
  462.             kfree(inp);
  463.             kfree(b);
  464.             if (outp) kfree(outp);
  465.             return ENSMEM;
  466.         }
  467.         tty->use_cnt = 0;
  468.             /* do_open does the rest of tty initialization */
  469.     } else tty = 0;
  470.  
  471. /* set up the pipes appropriately */
  472.     inp->head = inp->tail = 0;
  473.     inp->readers = selfread ? 1 : VIRGIN_PIPE; inp->writers = 1;
  474.     inp->rsel = inp->wsel = 0;
  475.     if (outp) {
  476.         outp->head = outp->tail = 0;
  477.         outp->readers = 1; outp->writers = selfread ? 1 : VIRGIN_PIPE;
  478.         outp->wsel = outp->rsel = 0;
  479.     }
  480.     strncpy(b->name, name, NAME_MAX);
  481.     b->time = timestamp;
  482.     b->date = datestamp;
  483.     b->dosflags = attrib;
  484.     b->mode = ((attrib & FA_SYSTEM) ? S_IFCHR : S_IFIFO) | mode;
  485.     b->uid = curproc->ruid;
  486.     b->gid = curproc->rgid;
  487.  
  488. /* the O_HEAD flag indicates that the file hasn't actually been opened
  489.  * yet; the next open gets to be the pty master. pipe_open will
  490.  * clear the flag when this happens.
  491.  */
  492.     b->flags = ((attrib & FA_SYSTEM) ? O_TTY : 0) | O_HEAD;
  493.     b->inp = inp; b->outp = outp; b->tty = tty;
  494.  
  495.     b->next = rootlist;
  496.     b->open = (FILEPTR *)0;
  497.     rootlist = b;
  498.  
  499. /* we have to return a file cookie as well */
  500.     fc->fs = &pipe_filesys;
  501.     fc->index = (long)b;
  502.     fc->dev = dir->dev;
  503.  
  504. /* update time/date stamps for u:\pipe */
  505.     pipetime = timestamp;
  506.     pipedate = datestamp;
  507.  
  508.     return 0;
  509. }
  510.  
  511. static DEVDRV * ARGS_ON_STACK 
  512. pipe_getdev(fc, devsp)
  513.     fcookie *fc;
  514.     long *devsp;
  515. {
  516.     struct fifo *b = (struct fifo *)fc->index;
  517.  
  518.     UNUSED(devsp);
  519.     return (b->flags & O_TTY) ? &pty_device : &pipe_device;
  520. }
  521.  
  522. /*
  523.  * PIPE device driver
  524.  */
  525.  
  526. static long ARGS_ON_STACK 
  527. pipe_open(f)
  528.     FILEPTR *f;
  529. {
  530.     struct fifo *p;
  531.     int rwmode = f->flags & O_RWMODE;
  532.  
  533.     p = (struct fifo *)f->fc.index;
  534.     f->flags |= p->flags;
  535. /*
  536.  * if this is the first open for this file, then the O_HEAD flag is
  537.  * set in p->flags. If not, and someone was trying to create the file,
  538.  * return an error
  539.  */
  540.     if (p->flags & O_HEAD) {
  541.         if (!(f->flags & O_CREAT)) {
  542.             DEBUG(("pipe_open: file hasn't been created yet"));
  543.             return EINTRN;
  544.         }
  545.         p->flags &= ~O_HEAD;
  546.     } else {
  547.         if (f->flags & O_CREAT) {
  548.             DEBUG(("pipe_open: fifo already exists"));
  549.             return EACCDN;
  550.         }
  551.     }
  552. /*
  553.  * check for file sharing compatibility. note that O_COMPAT gets mutated
  554.  * into O_DENYNONE, because any old programs that know about pipes will
  555.  * already handle multitasking correctly
  556.  */
  557.     if ( (f->flags & O_SHMODE) == O_COMPAT ) {
  558.         f->flags = (f->flags & ~O_SHMODE) | O_DENYNONE;
  559.     }
  560.     if (denyshare(p->open, f))
  561.         return EACCDN;
  562.     f->next = p->open;        /* add this open fileptr to the list */
  563.     p->open = f;
  564.  
  565. /*
  566.  * add readers/writers to the list
  567.  */
  568.     if (!(f->flags & O_HEAD)) {
  569.         if (rwmode == O_RDONLY || rwmode == O_RDWR) {
  570.             if (p->inp->readers == VIRGIN_PIPE)
  571.                 p->inp->readers = 1;
  572.             else
  573.                 p->inp->readers++;
  574.         }
  575.         if ((rwmode == O_WRONLY || rwmode == O_RDWR) && p->outp) {
  576.             if (p->outp->writers == VIRGIN_PIPE)
  577.                 p->outp->writers = 1;
  578.             else
  579.                 p->outp->writers++;
  580.         }
  581.     }
  582.  
  583. /* TTY devices need a tty structure in f->devinfo */
  584.     f->devinfo = (long)p->tty;
  585.  
  586.     return 0;
  587. }
  588.  
  589. static long ARGS_ON_STACK 
  590. pipe_write(f, buf, nbytes)
  591.     FILEPTR *f; const char *buf; long nbytes;
  592. {
  593.     int ptail, phead, j;
  594.     char *pbuf;
  595.     struct pipe *p;
  596.     struct fifo *this;
  597.     long bytes_written = 0;
  598.     long r;
  599.  
  600.     this = (struct fifo *)f->fc.index;
  601.     p = (f->flags & O_HEAD) ? this->inp : this->outp;
  602.     if (!p) {
  603.         DEBUG(("pipe_write: write on wrong end of pipe"));
  604.         return EACCDN;
  605.     }
  606.  
  607.     if (nbytes > 0 && nbytes <= PIPE_BUF) {
  608. check_atomicity:
  609.         r = p->tail - p->head;
  610.         if (r < 0) r += PIPESIZ;
  611.         r = (PIPESIZ-1) - r; /* r is the number of bytes we can write */
  612.         if (r < nbytes) {
  613.     /* check for broken pipes */
  614.             if (p->readers == 0 || p->readers == VIRGIN_PIPE) {
  615.                 check_sigs();
  616.                 DEBUG(("pipe_write: broken pipe"));
  617.                 raise(SIGPIPE);
  618.                 return EPIPE;
  619.             }
  620. /* wake up any readers, and wait for them to gobble some data */
  621.             if (p->rsel) {
  622.                 wakeselect(p->rsel);
  623.                 p->rsel = 0;
  624.             }
  625.             wake(IO_Q, (long)p);
  626.             sleep(IO_Q, (long)p);
  627.             goto check_atomicity;
  628.         }
  629.     }
  630.  
  631.     while (nbytes > 0) {
  632.         ptail = p->tail; phead = p->head;
  633.         j = ptail+1;
  634.         if (j >= PIPESIZ) j = 0;
  635.         if (j != phead) {
  636.             pbuf = &p->buf[ptail];
  637.             do {
  638.                 *pbuf++ = *buf++;
  639.                 nbytes--; bytes_written++;
  640.                 if ( (ptail = j) == 0 )
  641.                     pbuf = &p->buf[0];
  642.                 j++;
  643.                 if (j >= PIPESIZ) j = 0;
  644.             } while ( (nbytes > 0) && (j != phead) );
  645.             p->tail = ptail;
  646.         } else {        /* pipe full */
  647.             if (p->readers == 0 || p->readers == VIRGIN_PIPE) {
  648.             /* maybe some other signal is waiting for us? */
  649.                 check_sigs();
  650.                 DEBUG(("pipe_write: broken pipe"));
  651.                 raise(SIGPIPE);
  652.                 return EPIPE;
  653.             }
  654.             if (f->flags & O_NDELAY) {
  655.                 break;
  656.             }
  657.     /* is someone select()ing the other end of the pipe for reading? */
  658.             if (p->rsel) {
  659.                 wakeselect(p->rsel);
  660.                 p->rsel = 0;
  661.             }
  662.             wake(IO_Q, (long)p);    /* readers may continue */
  663. DEBUG(("pipe_write: sleep on %lx", p));
  664.             sleep(IO_Q, (long)p);
  665.         }
  666.     }
  667.     this->time = timestamp;
  668.     this->date = datestamp;
  669.     if (bytes_written > 0) {
  670.         if (p->rsel) {
  671.             wakeselect(p->rsel);
  672.             p->rsel = 0;
  673.         }
  674.         wake(IO_Q, (long)p);    /* maybe someone wants this data */
  675.     }
  676.  
  677.     return bytes_written;
  678. }
  679.  
  680. static long ARGS_ON_STACK 
  681. pipe_read(f, buf, nbytes)
  682.     FILEPTR *f; char *buf; long nbytes;
  683. {
  684.     int phead, ptail;
  685.     struct fifo *this;
  686.     struct pipe *p;
  687.     long bytes_read = 0;
  688.     char *pbuf;
  689.  
  690.     this = (struct fifo *)f->fc.index;
  691.     p = (f->flags & O_HEAD) ? this->outp : this->inp;
  692.     if (!p) {
  693.         DEBUG(("pipe_read: read on the wrong end of a pipe"));
  694.         return EACCDN;
  695.     }
  696.  
  697.     while (nbytes > 0) {
  698.         phead = p->head; ptail = p->tail;
  699.         if (ptail != phead) {
  700.             pbuf = &p->buf[phead];
  701.             do {
  702.                 *buf++ = *pbuf++;
  703.                 nbytes--; bytes_read++;
  704.                 phead++;
  705.                 if (phead >= PIPESIZ) {
  706.                     phead = 0;
  707.                     pbuf = &p->buf[phead];
  708.                 }
  709.             } while ( (nbytes > 0) && (phead != ptail) );
  710.             p->head = phead;
  711.         }
  712.         else if (p->writers <= 0 || p->writers == VIRGIN_PIPE) {
  713.             TRACE(("pipe_read: no more writers"));
  714.             break;
  715.         }
  716.         else if ((f->flags & O_NDELAY) ||
  717.                ((this->dosflags & FA_CHANGED) && bytes_read > 0) )
  718.         {
  719.             break;
  720.         }
  721.         else {
  722.     /* is someone select()ing the other end of the pipe for writing? */
  723.             if (p->wsel) {
  724.                 wakeselect(p->wsel);
  725.                 p->wsel = 0;
  726.             }
  727.             wake(IO_Q, (long)p);    /* writers may continue */
  728.             sleep(IO_Q, (long)p);
  729.         }
  730.     }
  731.     if (bytes_read > 0) {
  732.         if (p->wsel) {
  733.             wakeselect(p->wsel);
  734.             p->wsel = 0;
  735.         }
  736.         wake(IO_Q, (long)p);    /* wake writers */
  737.     }
  738.     return bytes_read;
  739. }
  740.  
  741. static long ARGS_ON_STACK 
  742. pipe_ioctl(f, mode, buf)
  743.     FILEPTR *f; int mode; void *buf;
  744. {
  745.     struct pipe *p;
  746.     struct fifo *this;
  747.     struct flock *lck;
  748.  
  749.     long r;
  750.  
  751.     this = (struct fifo *)f->fc.index;
  752.  
  753.     if (mode == FIONREAD) {
  754.             p = (f->flags & O_HEAD) ? this->outp : this->inp;
  755.             assert(p != 0);
  756.             if (p->writers <= 0 || p->writers == VIRGIN_PIPE) {
  757.                 DEBUG(("pipe FIONREAD: no writers"));
  758.                 r = -1;
  759.             } else {
  760.                 r = p->tail - p->head;
  761.                 if (r < 0) r += PIPESIZ;
  762.                 if (is_terminal(f))
  763.                     r = r >> 2;    /* r /= 4 */
  764.             }
  765.             *((long *) buf) = r;
  766.     }
  767.     else if (mode == FIONWRITE) {
  768.             p = (f->flags & O_HEAD) ? this->inp : this->outp;
  769.             assert(p != 0);
  770.             if (p->readers <= 0) {
  771.                 r = -1;
  772.             } else {
  773.                 r = p->tail - p->head;
  774.                 if (r < 0) r += PIPESIZ;
  775.                 r = (PIPESIZ-1) - r;
  776.                 if (is_terminal(f))
  777.                     r = r >> 2;    /* r /= 4 */
  778.             }
  779.             *((long *) buf) = r;
  780.     }
  781.     else if (mode == F_SETLK || mode == F_SETLKW) {
  782.         lck = (struct flock *)buf;
  783.         while (this->flags & O_LOCK) {
  784.             if (this->lockpid != curproc->pid) {
  785.                 DEBUG(("pipe_ioctl: pipe already locked"));
  786.                 if (mode == F_SETLKW && lck->l_type != F_UNLCK) {
  787.                     sleep(IO_Q, (long)this);        /* sleep a while */
  788.                 }
  789.                 else
  790.                     return ELOCKED;
  791.             } else
  792.                 break;
  793.         }
  794.         if (lck->l_type == F_UNLCK) {
  795.             if (!(f->flags & O_LOCK)) {
  796.                 DEBUG(("pipe_ioctl: wrong file descriptor for UNLCK"));
  797.                 return ENSLOCK;
  798.             }
  799.             this->flags &= ~O_LOCK;
  800.             this->lockpid = 0;
  801.             f->flags &= ~O_LOCK;
  802.             wake(IO_Q, (long)this);    /* wake up anyone waiting on the lock */
  803.         }
  804.         else {
  805.             this->flags |= O_LOCK;
  806.             this->lockpid = curproc->pid;
  807.             f->flags |= O_LOCK;
  808.         }
  809.     }
  810.     else if (mode == F_GETLK) {
  811.         lck = (struct flock *)buf;
  812.         if (this->flags & O_LOCK) {
  813.             lck->l_type = F_WRLCK;
  814.             lck->l_start = lck->l_len = 0;
  815.             lck->l_pid = this->lockpid;
  816.         }
  817.         else
  818.             lck->l_type = F_UNLCK;
  819.     }
  820.     else if (mode == TIOCFLUSH) {
  821.         long flushtype;
  822.         long *which;
  823.  
  824.         which = (long *)buf;
  825.         if (!which || !(*which & 3))
  826.             flushtype = 3;
  827.         else
  828.             flushtype = *which;
  829.  
  830.         if ((flushtype & 1) && this->inp) {
  831.             this->inp->head = this->inp->tail;
  832.             wake(IO_Q, (long)this->inp);
  833.         }
  834.         if ((flushtype & 2) && this->outp) {
  835.             this->outp->head = this->outp->tail;
  836.             wake(IO_Q, (long)this->outp);
  837.         }
  838.     } else if (mode == TIOCOUTQ) {
  839.             p = (f->flags & O_HEAD) ? this->inp : this->outp;
  840.             assert(p != 0);
  841.             if (p->readers <= 0) {
  842.                 r = -1;
  843.             } else {
  844.                 r = p->tail - p->head;
  845.                 if (r < 0) r += PIPESIZ;
  846.                 if (is_terminal(f))
  847.                     r = r >> 2;    /* r /= 4 */
  848.             }
  849.             *((long *) buf) = r;
  850.     } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) {
  851.         *(long *)buf = -1L;
  852.     } else if (mode == TIOCGFLAGS) {
  853.         *((unsigned short *)buf) = 0;
  854.     } else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
  855.     /* kludge: this assumes TOSWIN style escape sequences */
  856.         tty_putchar(f, (long)'\033', RAW);
  857.         switch (mode) {
  858.         case TCURSOFF:
  859.             tty_putchar(f, (long)'f', RAW);
  860.             break;
  861.         case TCURSON:
  862.             tty_putchar(f, (long)'e', RAW);
  863.             break;
  864.         case TCURSSRATE:
  865.             this->cursrate = *((int *)buf);
  866.             /* fall through */
  867.         case TCURSBLINK:
  868.             tty_putchar(f, (long)'t', RAW);
  869.             tty_putchar(f, (long)this->cursrate+32, RAW);
  870.             break;
  871.         case TCURSSTEADY:
  872.             tty_putchar(f, (long)'t', RAW);
  873.             tty_putchar(f, (long)32, RAW);
  874.             break;
  875.         case TCURSGRATE:
  876.             return this->cursrate;
  877.         }
  878.     } else {
  879.     /* if the file is a terminal, Fcntl will automatically
  880.      * call tty_ioctl for us to handle 'generic' terminal
  881.      * functions
  882.      */
  883.         return EINVFN;
  884.     }
  885.  
  886.     return 0;
  887. }
  888.  
  889. static long ARGS_ON_STACK 
  890. pipe_lseek(f, where, whence)
  891.     FILEPTR *f; long where; int whence;
  892. {
  893.     UNUSED(f); UNUSED(where); UNUSED(whence);
  894.     return EACCDN;
  895. }
  896.  
  897. static long ARGS_ON_STACK 
  898. pipe_datime(f, timeptr, rwflag)
  899.     FILEPTR *f;
  900.     short *timeptr;
  901.     int rwflag;
  902. {
  903.     struct fifo *this;
  904.  
  905.     this = (struct fifo *)f->fc.index;
  906.     if (rwflag) {
  907.         this->time = timeptr[0];
  908.         this->date = timeptr[1];
  909.     }
  910.     else {
  911.         timeptr[0] = this->time;
  912.         timeptr[1] = this->date;
  913.     }
  914.     return 0;
  915. }
  916.  
  917. static long ARGS_ON_STACK 
  918. pipe_close(f, pid)
  919.     FILEPTR *f;
  920.     int pid;
  921. {
  922.     struct fifo *this, *old;
  923.     struct pipe *p;
  924.     int rwmode;
  925.     FILEPTR **old_x, *x;
  926.  
  927.     this = (struct fifo *)f->fc.index;
  928.  
  929. /* wake any processes waiting on this pipe */
  930.     wake(IO_Q, (long)this->inp);
  931.     if (this->inp->rsel)
  932.         wakeselect(this->inp->rsel);
  933.     if (this->inp->wsel)
  934.         wakeselect(this->inp->wsel);
  935.  
  936.     if (this->outp) {
  937.         wake(IO_Q, (long)this->outp);
  938.         if (this->outp->wsel)
  939.             wakeselect(this->outp->wsel);
  940.         if (this->outp->rsel)
  941.             wakeselect(this->outp->rsel);
  942.     }
  943.  
  944.     if (f->links <= 0) {
  945. /* remove the file pointer from the list of open file pointers 
  946.  * of this pipe
  947.  */
  948.         old_x = &this->open;
  949.         x = this->open;
  950.         while (x && x != f) {
  951.                 old_x = &x->next;
  952.                 x = x->next;
  953.         }
  954.         assert(x);
  955.         *old_x = f->next;
  956.         /* f->next = 0; */
  957.  
  958.         rwmode = f->flags & O_RWMODE;
  959.         if (rwmode == O_RDONLY || rwmode == O_RDWR) {
  960.             p = (f->flags & O_HEAD) ? this->outp : this->inp;
  961. /* note that this can never be a virgin pipe, since we had a handle
  962.  * on it!
  963.  */            if (p)
  964.                 p->readers--;
  965.         }
  966.         if (rwmode == O_WRONLY || rwmode == O_RDWR) {
  967.             p = (f->flags & O_HEAD) ? this->inp : this->outp;
  968.             if (p) p->writers--;
  969.         }
  970.  
  971. /* correct for the "selfread" flag (see pipe_creat) */
  972.         if ((f->flags & O_HEAD) && !(this->dosflags & 0x02))
  973.             this->inp->readers--;
  974.  
  975. /* check for locks */
  976.         if ((f->flags & O_LOCK) && (this->lockpid == pid)) {
  977.             this->flags &= ~O_LOCK;
  978.             wake(IO_Q, (long)this);    /* wake up anyone waiting on the lock */
  979.         }
  980.     }
  981.  
  982. /* see if we're finished with the pipe */
  983.     if (this->inp->readers == VIRGIN_PIPE)
  984.         this->inp->readers = 0;
  985.     if (this->inp->writers == VIRGIN_PIPE)
  986.         this->inp->writers = 0;
  987.  
  988.     if (this->inp->readers <= 0 && this->inp->writers <= 0) {
  989.         TRACE(("disposing of closed fifo"));
  990. /* unlink from list of FIFOs */
  991.         if (rootlist == this)
  992.             rootlist = this->next;
  993.         else {
  994.             for (old = rootlist; old->next != this;
  995.                     old = old->next) {
  996.                 if (!old) {
  997.                     ALERT("fifo not on list???");
  998.                     return EINTRN;
  999.                 }
  1000.             }
  1001.             old->next = this->next;
  1002.         }
  1003.         kfree(this->inp);
  1004.         if (this->outp) kfree(this->outp);
  1005.         if (this->tty) kfree(this->tty);
  1006.         kfree(this);
  1007.         pipetime = timestamp;
  1008.         pipedate = datestamp;
  1009.     }
  1010.  
  1011.     return 0;
  1012. }
  1013.  
  1014. static long ARGS_ON_STACK 
  1015. pipe_select(f, proc, mode)
  1016.     FILEPTR *f;
  1017.     long proc;
  1018.     int mode;
  1019. {
  1020.     struct fifo *this;
  1021.     struct pipe *p;
  1022.     int j;
  1023.  
  1024.     this = (struct fifo *)f->fc.index;
  1025.  
  1026.     if (mode == O_RDONLY) {
  1027.         p = (f->flags & O_HEAD) ? this->outp : this->inp;
  1028.         if (!p) {
  1029.             DEBUG(("read select on wrong end of pipe"));
  1030.             return 0;
  1031.         }
  1032.  
  1033. /* NOTE: if p->writers <= 0 then reads won't block (they'll fail) */
  1034.         if (p->tail != p->head || p->writers <= 0) {
  1035.             return 1;
  1036.         }
  1037.  
  1038.         if (p->rsel)
  1039.             return 2;    /* collision */
  1040.         p->rsel = proc;
  1041.         return 0;
  1042.     } else if (mode == O_WRONLY) {
  1043.         p = (f->flags & O_HEAD) ? this->inp : this->outp;
  1044.         if (!p) {
  1045.             DEBUG(("write select on wrong end of pipe"));
  1046.             return 0;
  1047.         }
  1048.         j = p->tail+1;
  1049.         if (j >= PIPESIZ) j = 0;
  1050.         if (j != p->head || p->readers <= 0)
  1051.             return 1;    /* data may be written */
  1052.         if (p->wsel)
  1053.             return 2;    /* collision */
  1054.         p->wsel = proc;
  1055.         return 0;
  1056.     }
  1057.     return 0;
  1058. }
  1059.  
  1060. static void ARGS_ON_STACK 
  1061. pipe_unselect(f, proc, mode)
  1062.     FILEPTR *f;
  1063.     long proc;
  1064.     int mode;
  1065. {
  1066.     struct fifo *this;
  1067.     struct pipe *p;
  1068.  
  1069.     this = (struct fifo *)f->fc.index;
  1070.  
  1071.     if (mode == O_RDONLY) {
  1072.         p = (f->flags & O_HEAD) ? this->outp : this->inp;
  1073.         if (!p) {
  1074.             return;
  1075.         }
  1076.         if (p->rsel == proc)
  1077.             p->rsel = 0;
  1078.     } else if (mode == O_WRONLY) {
  1079.         p = (f->flags & O_HEAD) ? this->inp : this->outp;
  1080.         if (!p) {
  1081.             return;
  1082.         }
  1083.         if (p->wsel == proc)
  1084.             p->wsel = 0;
  1085.     }
  1086. }
  1087.